package utils

import (
	"errors"
	"github.com/go-resty/resty/v2"
	"github.com/sirupsen/logrus"
	"net/url"
	"strings"
)

type Param struct {
	Client      *resty.Client
	IsNewClient bool //是否每次请求重新new client
	PrevFunc    []func(*Param)
	ParseFunc   []func(*Param, *resty.Response)
	Session     *SessionManage
	NextUrl     string
	Request     map[string]*DoReq
	Account     Account
	TempMap     map[string]interface{}
	Err         error
}
type Account struct {
	UserName string
	Password string
}
type DoReq struct {
	Url      string
	Type     int //1 json 2 fromValue
	Method   string
	Body     interface{}
	Value    url.Values
	FormData map[string]string
}

const (
	Json      = 1
	FormValue = 2
	FormData  = 3
)

func NewParam(isNewClient bool) *Param {
	return &Param{
		Client:      resty.New().SetRedirectPolicy(resty.NoRedirectPolicy()),
		IsNewClient: isNewClient,
		Request:     map[string]*DoReq{},
		Session:     NewSessionManage(),
	}
}
func (p *Param) SetAccount(account Account) *Param {
	p.Account = account
	return p
}
func (p *Param) Do(options ...Option) *Param {
	p.clear()
	for _, option := range options {
		option(p)
	}
	if p.NextUrl == "" {
		p.Err = errors.New("参数错误")
		return p
	}
	if p.Err != nil {
		return p
	}
	for _, f := range p.PrevFunc {
		f(p)
	}

	client := p.Client
	r := client.R()
	if p.IsNewClient {
		client = resty.New().SetRedirectPolicy(resty.NoRedirectPolicy())
		r = client.R()
		r.SetCookies(p.Session.GetCookies(p.NextUrl))
	}
	r.SetHeaders(p.Session.GetHeader(p.NextUrl))
	d := p.Request[p.NextUrl]
	method := ""
	if d == nil {
		method = "GET"
	} else {
		method = strings.ToUpper(d.Method)

	}
	var res *resty.Response
	var err error
	switch method {
	case "GET":
		res, err = r.Get(p.NextUrl)
	case "POST":
		if d != nil {
			if d.Type == 1 {
				r = r.SetBody(d.Body)
			} else if d.Type == 2 {
				r = r.SetFormDataFromValues(d.Value)
			} else if d.Type == 3 {
				r = r.SetFormData(d.FormData)
			}
		}
		res, err = r.Post(p.NextUrl)
	case "PUT":
		res, err = r.Put(p.NextUrl)
	case "DELETE":
		res, err = r.Delete(p.NextUrl)
	}
	if err != nil && !strings.Contains(err.Error(), "auto redirect is disabled") {
		p.Err = err
		return p
	}
	if res.StatusCode() == 200 {
		logrus.Infof("resp:%s", string(res.Body()))
	} else if res.StatusCode() == 302 {
		logrus.Infof("location:%s", res.Header().Get("location"))
	}

	p.Session.SetCookies(p.NextUrl, res.Cookies())
	for _, f := range p.ParseFunc {
		f(p, res)
	}
	return p
}

type Option func(p *Param) *Param

func (p *Param) clear() {
	p.ParseFunc = []func(*Param, *resty.Response){}
	p.PrevFunc = []func(*Param){}
	return
}
func WithParseFunc(parseFunc func(*Param, *resty.Response)) Option {
	return func(p *Param) *Param {
		p.ParseFunc = append(p.ParseFunc, parseFunc)
		return p
	}
}
func WithPrevFunc(prevFunc func(*Param)) Option {
	return func(p *Param) *Param {
		p.PrevFunc = append(p.PrevFunc, prevFunc)
		return p
	}
}
func WithUrl(nextUrl string) Option {
	return func(p *Param) *Param {
		p.NextUrl = nextUrl
		return p
	}
}
